package rpcserver

import (
    "net"
    "errors"

    "git.edaijia-inc.cn/edaijia/ego/elogger"

    "google.golang.org/grpc"
    "github.com/sirupsen/logrus"
    "github.com/grpc-ecosystem/go-grpc-middleware"
    "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
    "github.com/grpc-ecosystem/go-grpc-middleware/tags"
)

type RegisterFunc func(*grpc.Server) error

type RpcServer struct {
    GRpcServer *grpc.Server
    TcpListen net.Listener
}

func NewRpcServer(rpcAddr string, registerFunc RegisterFunc) (*RpcServer, error) {
    opts := []grpc.ServerOption{}

    log := elogger.GetELogger()
    if log != nil {
        //log middleware
        logrusEntry := logrus.NewEntry(log)
        opts = append(opts,grpc_middleware.WithUnaryServerChain(
            grpc_ctxtags.UnaryServerInterceptor(),
            grpc_logrus.UnaryServerInterceptor(logrusEntry),
        ))
        opts = append(opts, grpc_middleware.WithStreamServerChain(
            grpc_ctxtags.StreamServerInterceptor(),
            grpc_logrus.StreamServerInterceptor(logrusEntry),
        ))
    }

    lis, err := net.Listen("tcp", rpcAddr)
    if err != nil {
        elogger.Panicf("failed to listen: %v", err)
        return nil, err
    }
    grpcServer := grpc.NewServer(opts...)
    err = registerFunc(grpcServer)
    if err != nil {
        elogger.Panicf("failed to register: %v", err)
        return nil, err
    }

    return &RpcServer{grpcServer, lis}, nil
}

func (s *RpcServer) Run(block bool) error {
    if s.GRpcServer == nil {
        return errors.New("RpcServer GRpcServer is nil")
    }

    if block {
        return s.GRpcServer.Serve(s.TcpListen)
    } else {
        go func() {
            if err := s.GRpcServer.Serve(s.TcpListen); err != nil {
                elogger.Panicf("failed to serve: %v", err)
            }
        }()
    }

    return nil
}
